using System;
using System.Threading;
using System.Diagnostics;

namespace GoodStuff
{
    public class WorkerThread
    {
        protected Thread			_workerThread;
	    protected bool				_run;
	    protected ManualResetEvent	_pause;
	    protected ManualResetEvent	_paused;

        public WorkerThread()
        {
            _workerThread = null;
            _run = false;
            
	        Trace.WriteLine("WorkerThread: counstructor called");
        }
        public Thread CreateThread(String name, ThreadPriority p)
        {
	        Trace.WriteLine("WorkerThread: CreateThread " + name);

	        ThreadStart ts = new ThreadStart(ThreadProc);
	        _workerThread = new Thread(ts);	
	        _workerThread.Priority = p;
	        _workerThread.Name = name;

	        _pause  = new ManualResetEvent(true);
	        _paused = new ManualResetEvent(false);

	        return _workerThread;
        }
        public void StartThread()
        {
	        if( _workerThread == null )
		        CreateThread("Default Worker Thread Name", ThreadPriority.Normal);

	        Trace.WriteLine("WorkerThread: StartThread " + _workerThread.Name);

	        _pause.Set();
	        _paused.Reset();
	        _run = true;
	        _workerThread.Start();
        }
        public void StopThread()
        {
            StopThread(250);
        }
        public void StopThread(int timeout)
        {
            if(_workerThread != null)
            {
	            Trace.WriteLine("WorkerThread: StopThread " + _workerThread.Name);
	            if( _workerThread.IsAlive)
	            {
		            _run = false;
		            _workerThread.Join(timeout);

		            if( _workerThread.IsAlive)
		            {
			            _workerThread.Abort();
			            Trace.WriteLine(String.Concat("WorkerThread: had to abort thread ", _workerThread.Name ));
		            }
	            }
	            else
	            {
			            Trace.WriteLine(String.Concat("WorkerThread: StopThread called on dead thread ", _workerThread.Name ));
	            }
            }

        }
        public ManualResetEvent PauseThread()
        {
	        _pause.Reset();
	        return _paused;
        }
        public void ResumeThread()
        {
	        _pause.Set();
        }
        public Thread GetThread()
        {
	        return _workerThread;
        }
        protected bool KeepGoing()
        {
            return KeepGoing(100);
        }
        protected bool KeepGoing(int timeout)
        {
	        if(_run && !_pause.WaitOne(0, false))
	        {
		        _paused.Set();
		        while(_run && !_pause.WaitOne(timeout, false));
		        _paused.Reset();
	        }

	        return _run;
        }
        virtual protected void ThreadProc()
        {
        }
    }
}
